#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
基于简历的混合检索系统 - 简化演示版

这是一个不依赖外部库的演示版本，展示系统的核心逻辑和流程。
在实际使用中，请安装完整的依赖库。

功能：
1. 简历解析（简化版）
2. 关键信息提取
3. 混合检索模拟
4. LLM分析模拟
5. 推荐理由生成
6. 结果展示
"""

import re
import json
import random
from typing import List, Dict, Any, Optional


def simple_resume_parser(resume_text: str) -> Dict[str, Any]:
    """
    简化的简历解析器
    """
    print("📄 开始解析简历...")
    
    # 提取技能
    skills = []
    skill_keywords = [
        'Java', 'Python', 'JavaScript', 'React', 'Vue', 'Spring', 
        'MySQL', 'Redis', 'Docker', 'Git', 'Linux', 'AWS'
    ]
    
    for skill in skill_keywords:
        if skill.lower() in resume_text.lower():
            skills.append(skill)
    
    # 提取经验年限
    experience_patterns = [r'(\d+)\s*年.*?经验', r'工作.*?(\d+)\s*年']
    experience_years = 0
    
    for pattern in experience_patterns:
        matches = re.findall(pattern, resume_text)
        if matches:
            experience_years = int(matches[0])
            break
    
    # 提取教育背景
    education = '本科'
    if '硕士' in resume_text or '研究生' in resume_text:
        education = '硕士'
    elif '博士' in resume_text:
        education = '博士'
    
    # 提取期望地点
    cities = ['北京', '上海', '深圳', '杭州', '广州', '成都']
    preferred_location = None
    for city in cities:
        if city in resume_text:
            preferred_location = city
            break
    
    resume_info = {
        'skills': skills,
        'experience_years': experience_years,
        'education': education,
        'preferred_location': preferred_location,
        'raw_text': resume_text
    }
    
    print(f"✅ 简历解析完成：技能{len(skills)}项，经验{experience_years}年")
    return resume_info


def mock_es_search(resume_info: Dict[str, Any]) -> List[Dict[str, Any]]:
    """
    模拟ES关键词检索
    """
    print("🔍 执行ES关键词检索...")
    
    # 模拟职位数据
    mock_jobs = [
        {
            "job_id": "es_001",
            "title": "Java开发工程师",
            "company_name": "阿里巴巴",
            "city_name": "杭州",
            "money": "20-30K",
            "description": "负责Java后端开发，要求熟练掌握Spring Boot、MySQL等技术",
            "es_score": 8.5
        },
        {
            "job_id": "es_002", 
            "title": "Python开发工程师",
            "company_name": "腾讯",
            "city_name": "深圳",
            "money": "25-35K",
            "description": "负责Python后端开发，熟悉Django、Redis等技术",
            "es_score": 7.8
        },
        {
            "job_id": "es_003",
            "title": "前端开发工程师",
            "company_name": "字节跳动",
            "city_name": "北京",
            "money": "18-28K",
            "description": "负责前端开发，要求熟练掌握React、Vue、JavaScript",
            "es_score": 7.2
        }
    ]
    
    # 根据简历技能计算匹配分数
    for job in mock_jobs:
        skill_matches = 0
        for skill in resume_info['skills']:
            if skill.lower() in job['description'].lower() or skill.lower() in job['title'].lower():
                skill_matches += 1
        
        # 调整分数
        job['es_score'] = max(5.0, job['es_score'] - (3 - skill_matches) * 0.5)
    
    # 按分数排序
    mock_jobs.sort(key=lambda x: x['es_score'], reverse=True)
    
    print(f"✅ ES检索完成，找到{len(mock_jobs)}个相关职位")
    return mock_jobs


def mock_milvus_search(resume_info: Dict[str, Any]) -> List[Dict[str, Any]]:
    """
    模拟Milvus语义检索
    """
    print("🧠 执行Milvus语义检索...")
    
    # 模拟语义相似的职位
    mock_jobs = [
        {
            "job_id": "vec_001",
            "title": "后端开发工程师",
            "company_name": "美团",
            "city_name": "北京",
            "money": "22-32K",
            "description": "负责后端系统开发和架构设计",
            "vector_score": 0.92
        },
        {
            "job_id": "vec_002",
            "title": "全栈开发工程师", 
            "company_name": "京东",
            "city_name": "北京",
            "money": "20-30K",
            "description": "负责前后端开发，技术栈包括Java、React",
            "vector_score": 0.88
        },
        {
            "job_id": "vec_003",
            "title": "软件开发工程师",
            "company_name": "百度",
            "city_name": "北京", 
            "money": "24-34K",
            "description": "负责软件系统开发，要求扎实编程基础",
            "vector_score": 0.85
        }
    ]
    
    # 基于技能数量调整相似度分数
    skill_count = len(resume_info['skills'])
    for job in mock_jobs:
        job['vector_score'] = min(0.95, job['vector_score'] + skill_count * 0.01)
    
    print(f"✅ Milvus检索完成，找到{len(mock_jobs)}个语义相似职位")
    return mock_jobs


def merge_and_rank_simple(es_results: List[Dict], milvus_results: List[Dict]) -> List[Dict]:
    """
    简化的结果融合和排序
    """
    print("🔄 开始结果融合...")
    
    # 构建职位索引
    job_index = {}
    
    # 处理ES结果
    for job in es_results:
        job_id = job['job_id']
        job_index[job_id] = {
            **job,
            'vector_score': 0,
            'has_es': True,
            'has_vector': False
        }
    
    # 处理Milvus结果
    for job in milvus_results:
        job_id = job['job_id']
        if job_id in job_index:
            job_index[job_id]['vector_score'] = job['vector_score']
            job_index[job_id]['has_vector'] = True
        else:
            job_index[job_id] = {
                **job,
                'es_score': 0,
                'has_es': False,
                'has_vector': True
            }
    
    # 归一化和融合分数
    all_jobs = list(job_index.values())
    es_max = max([job.get('es_score', 0) for job in all_jobs]) or 1
    vec_max = max([job.get('vector_score', 0) for job in all_jobs]) or 1
    
    for job in all_jobs:
        norm_es = job.get('es_score', 0) / es_max
        norm_vec = job.get('vector_score', 0) / vec_max
        
        # 加权融合 (ES 40%, Milvus 60%)
        base_score = 0.4 * norm_es + 0.6 * norm_vec
        
        # 双重匹配加分
        if job.get('has_es') and job.get('has_vector'):
            job['final_score'] = base_score * 1.2
            job['is_complementary'] = True
        else:
            job['final_score'] = base_score
            job['is_complementary'] = False
    
    # 排序
    all_jobs.sort(key=lambda x: x['final_score'], reverse=True)
    
    print(f"✅ 结果融合完成，最终{len(all_jobs)}个职位")
    return all_jobs


def mock_llm_analysis(resume_info: Dict[str, Any], job: Dict[str, Any]) -> Dict[str, Any]:
    """
    模拟LLM分析
    """
    
    # 简单的匹配度计算
    skill_match = 5
    for skill in resume_info['skills']:
        if skill.lower() in job.get('description', '').lower():
            skill_match += 1
    skill_match = min(10, skill_match)
    
    # 经验匹配
    exp_years = resume_info['experience_years']
    if exp_years == 0:
        experience_match = 8 if '初级' in job.get('title', '') else 6
    elif exp_years <= 3:
        experience_match = 8
    else:
        experience_match = 9 if '高级' in job.get('title', '') else 7
    
    # 地理匹配
    location_match = 10 if resume_info.get('preferred_location') == job.get('city_name') else 6
    
    # 综合匹配度
    overall_match = round((skill_match + experience_match + location_match) / 3)
    
    return {
        'skill_match': skill_match,
        'experience_match': experience_match,
        'development_match': 7,
        'location_match': location_match,
        'salary_match': 7,
        'overall_match': overall_match,
        'recommendation_reason': f"技能匹配{skill_match}/10，经验匹配{experience_match}/10，综合评估优秀"
    }


def generate_reasons_simple(job: Dict[str, Any], resume_info: Dict[str, Any], llm_analysis: Dict[str, Any]) -> List[str]:
    """
    简化的推荐理由生成
    """
    reasons = []
    
    # 技能匹配理由
    matched_skills = []
    for skill in resume_info['skills']:
        if skill.lower() in job.get('description', '').lower():
            matched_skills.append(skill)
    
    if matched_skills:
        reasons.append(f"🎯 您掌握的{'/'.join(matched_skills[:3])}技能与职位要求匹配")
    
    # 经验理由
    exp_years = resume_info['experience_years']
    if exp_years == 0:
        reasons.append("🎓 适合应届毕业生，是职业生涯的好起点")
    elif exp_years <= 3:
        reasons.append(f"📈 您的{exp_years}年经验符合职位要求")
    else:
        reasons.append(f"🚀 您的{exp_years}年丰富经验完全胜任此职位")
    
    # 公司理由
    company = job.get('company_name', '')
    if company in ['阿里巴巴', '腾讯', '字节跳动', '美团', '京东', '百度']:
        reasons.append(f"🏢 {company}是知名企业，平台优秀发展前景好")
    
    # 地理理由
    if resume_info.get('preferred_location') == job.get('city_name'):
        reasons.append(f"📍 工作地点{job.get('city_name')}符合您的期望")
    
    # LLM分析理由
    if llm_analysis['overall_match'] >= 8:
        reasons.append(f"🤖 AI分析显示高度匹配({llm_analysis['overall_match']}/10分)")
    
    # 系统推荐理由
    if job.get('is_complementary'):
        reasons.append("⭐ 多维度匹配，系统强烈推荐")
    
    return reasons[:3]  # 最多3个理由


def display_results_simple(recommendations: List[Dict[str, Any]], resume_info: Dict[str, Any]):
    """
    简化的结果展示
    """
    print("\n" + "=" * 60)
    print("📋 简历分析结果")
    print("=" * 60)
    print(f"🎓 教育背景: {resume_info['education']}")
    print(f"💼 工作经验: {resume_info['experience_years']} 年")
    print(f"💻 掌握技能: {', '.join(resume_info['skills'][:8])}...")
    print(f"📍 期望地点: {resume_info['preferred_location'] or '未指定'}")
    
    print("\n" + "=" * 60)
    print("🎯 推荐职位列表")
    print("=" * 60)
    
    for i, rec in enumerate(recommendations[:10]):
        job = rec['job_info']
        analysis = rec['llm_analysis'] 
        reasons = rec['reasons']
        
        print(f"\n【{i+1}】{job.get('title', '')} @ {job.get('company_name', '')}")
        print(f"   📍 地点: {job.get('city_name', '')}   💰 薪资: {job.get('money', '')}")
        print(f"   ⭐ 匹配度: {analysis['overall_match']}/10   🔥 系统评分: {job.get('final_score', 0):.3f}")
        print(f"   💡 推荐理由:")
        
        for j, reason in enumerate(reasons[:2]):
            print(f"      {j+1}. {reason}")
        
        print(f"   📝 职位描述: {job.get('description', '')[:80]}...")


def main_demo():
    """
    主演示函数
    """
    print("🎯 基于简历的混合检索推荐系统 - 演示版")
    print("=" * 50)
    
    # 示例简历
    sample_resume = """
    张三的个人简历
    
    基本信息：
    姓名：张三
    年龄：26岁
    学历：本科
    专业：计算机科学与技术
    期望地点：北京
    期望薪资：20-25K
    
    工作经验：
    2020年-至今  某科技公司  Java开发工程师  3年
    - 负责后端系统开发
    - 使用Java、Spring Boot、MySQL、Redis等技术
    
    技能清单：
    编程语言：Java、Python、JavaScript
    框架技术：Spring、React、Vue
    数据库：MySQL、Redis
    工具平台：Git、Docker
    """
    
    print("📄 使用示例简历进行演示...")
    
    # Step 1: 简历解析
    resume_info = simple_resume_parser(sample_resume)
    
    # Step 2: 混合检索
    es_results = mock_es_search(resume_info)
    milvus_results = mock_milvus_search(resume_info)
    
    # Step 3: 结果融合
    merged_results = merge_and_rank_simple(es_results, milvus_results)
    
    # Step 4: LLM分析和推荐理由生成
    print("\n🤖 开始LLM分析和推荐理由生成...")
    recommendations = []
    
    for i, job in enumerate(merged_results[:8]):  # 分析前8个职位
        llm_analysis = mock_llm_analysis(resume_info, job)
        reasons = generate_reasons_simple(job, resume_info, llm_analysis)
        
        recommendation = {
            'job_info': job,
            'llm_analysis': llm_analysis,
            'reasons': reasons,
            'ranking': i + 1
        }
        
        recommendations.append(recommendation)
    
    # Step 5: 结果展示
    display_results_simple(recommendations, resume_info)
    
    # 统计信息
    avg_match = sum(rec['llm_analysis']['overall_match'] for rec in recommendations) / len(recommendations)
    complementary_count = sum(1 for rec in recommendations if rec['job_info'].get('is_complementary'))
    
    print("\n" + "=" * 60)
    print("📊 推荐统计")
    print("=" * 60)
    print(f"📈 推荐职位数量: {len(recommendations)}")
    print(f"⭐ 平均匹配度: {avg_match:.1f}/10")
    print(f"🔥 双重匹配职位: {complementary_count}个")
    print(f"🏢 涉及公司: {len(set(rec['job_info']['company_name'] for rec in recommendations))}家")
    
    print("\n✅ 演示完成！这就是混合检索推荐系统的核心流程。")
    print("💡 实际系统会连接真实的ES、Milvus和LLM服务。")


if __name__ == "__main__":
    main_demo()
